package com.hsteach.service.visit;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

import com.alibaba.nacos.client.naming.utils.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.hsteach.common.constant.HttpStatus;
import com.hsteach.common.core.domain.model.AuthInfo;
import com.hsteach.common.core.page.TableDataInfo;
import com.hsteach.common.exception.ServiceException;
import com.hsteach.common.utils.DateUtils;
import com.hsteach.common.utils.SecurityUtils;
import com.hsteach.common.utils.StringUtils;
import com.hsteach.dao.domain.visit.*;
import com.hsteach.dao.mapper.visit.*;
import com.hsteach.enums.*;
import com.hsteach.framework.feign.client.xgk.dto.XgkListResp;
import com.hsteach.framework.feign.client.xgk.dto.ret.*;
import com.hsteach.service.third.XgkService;
import com.hsteach.web.controller.visit.dto.*;
import com.hsteach.web.controller.visit.vo.ClassStatisticsVo;
import com.hsteach.web.controller.visit.vo.ListRecordVo;
import com.hsteach.web.controller.visit.vo.VisitStatisticsVo;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 家访记录Service业务层处理
 *
 * @author fanxquer
 * @date 2023-07-21
 */
@Service
public class VisitRecordService extends ServiceImpl<VisitRecordMapper, VisitRecord> {
    @Autowired
    private VisitRecordMapper visitRecordMapper;

    @Autowired
    private VisitRecordTextMapper visitRecordTextMapper;

    @Autowired
    private VisitInterestTagMapper visitInterestTagMapper;

    @Autowired
    private VisitPeersMapper visitPeersMapper;

    @Autowired
    private VisitImgMapper visitImgMapper;

    @Autowired
    private VisitReservationMapper visitReservationMapper;

    @Autowired
    private VisitReservationService visitReservationService;

    @Autowired
    private XgkService xgkService;

    @Autowired
    private VisitInterestTagService visitInterestTagService;

    /**
     * 查询家访记录
     *
     * @param id 家访记录主键
     * @return 家访记录
     */
    public VisitRecord selectVisitRecordById(Long id) {
        return visitRecordMapper.selectVisitRecordById(id);
    }

    /**
     * 查询家访记录列表
     *
     * @param visitRecord 家访记录
     * @return 家访记录
     */
    public List<VisitRecord> selectVisitRecordList(VisitRecord visitRecord) {
        return visitRecordMapper.selectVisitRecordListV2(visitRecord);
    }

    public VisitStatisticsVo statistics(VisitStatisticsDto dto) {
        GetSchoolPartTreeRet schoolPartTree = xgkService.getSchoolPartTreeAuth(SecurityUtils.getAuthInfo().getPersonId());
        List<String> classIds = getClassIds(schoolPartTree, dto.getUnitType(), dto.getUnitId());
        List<GetClazzWithStudentsRet> clazzWithStudents = xgkService.getClazzWithStudents(SecurityUtils.getAuthInfo().getPersonId());

        if (classIds.size() == 0) {
            classIds = Lists.newArrayList("-1");
        }

        if (dto.getRange() == null || StatisticsRangeEnum.ALL.getCode().equals(dto.getRange())) {
            return statisticsAll(clazzWithStudents, classIds);
        } else if (StatisticsRangeEnum.INTEREST.getCode().equals(dto.getRange())) {
            return statisticsInterest(clazzWithStudents, classIds);
        } else {
            throw new ServiceException("不支持的统计范围");
        }
    }

    public VisitStatisticsVo statisticsAll(List<GetClazzWithStudentsRet> clazzWithStudents, List<String> classIds) {
        List<GetYearListRet> yearList = xgkService.getYearList(SecurityUtils.getAuthInfo().getOrgCode());
        if (yearList.isEmpty()) {
            throw new ServiceException("学年数据不存在");
        }
        long l = DateUtils.getNowyyyyMMdd().getTime();
        GetYearListRet curYear = yearList.stream().filter(e -> DateUtils.parseDate(e.getBeginDay()).getTime() <= l && DateUtils.parseDate(e.getEndDay()).getTime() >= l).findFirst().orElse(yearList.get(yearList.size() - 1));
        if (curYear == null) {
            throw new ServiceException("当前学年数据不存在");
        }
        List<VisitRecord> visitCount = visitRecordMapper.selectCountGroupByClassIds(classIds, DateUtils.parseDate(curYear.getBeginDay()), DateUtils.parseDate(curYear.getEndDay()));
        // 学生人数
        Integer allSum = clazzWithStudents.stream().filter(e -> classIds.contains(e.getClassId())).map(GetClazzWithStudentsRet::getStudentNum).reduce(new Integer(0), (v1, v2) -> v1 + v2);
        Map<String, Integer> classRealMap = visitCount.stream().collect(Collectors.groupingBy(VisitRecord::getClassId))
                .entrySet().stream().collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue().size()));
        // 去重后真实家访次数
        Integer realVisitSum = classRealMap.values().stream().reduce(new Integer(0), (v1, v2) -> v1 + v2);
        // 合计完成家访
        Integer visitSum = visitCount.stream().map(VisitRecord::getCount).reduce(new Integer(0), (v1, v2) -> v1 + v2);
        VisitStatisticsVo ret = new VisitStatisticsVo();
        if (allSum.equals(0)) {
            realVisitSum = 0;
            visitSum = 0;
        }
        // 生均家访次数
        if (visitSum.equals(0)) {
            ret.setAvgOne(BigDecimal.ZERO);
        } else {
            BigDecimal personAvg = BigDecimal.valueOf(visitSum).divide(BigDecimal.valueOf(allSum), 1, RoundingMode.HALF_UP);
            ret.setAvgOne(personAvg);
        }
        // 家访比例
//        BigDecimal visitRate = BigDecimal.valueOf(realVisitSum).divide(BigDecimal.valueOf(allSum), 3, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100));
        ret.setVisitSum(visitSum);
        ret.setVisitedSum(realVisitSum);
        ret.setNotVisitSum(allSum - realVisitSum);

        if (realVisitSum.equals(0)) {
            ret.setRate(BigDecimal.ZERO);
        } else {
            ret.setRate(BigDecimal.valueOf(realVisitSum).divide(BigDecimal.valueOf(allSum), 3, RoundingMode.HALF_UP).multiply(new BigDecimal(100)));
        }
        // 计算班级统计详情
        List<ClassStatisticsVo> classes = clazzWithStudents.stream().filter(e -> classIds.contains(e.getClassId())).map(e -> {
            ClassStatisticsVo vo = new ClassStatisticsVo();
            vo.setClassId(e.getClassId());
            vo.setClassName(e.getClassName());
            vo.setTeacherName(e.getTeacherName());
            Integer classVisitSum = visitCount.stream().filter(k -> e.getClassId().equals(k.getClassId()))
                    .map(VisitRecord::getCount).reduce(new Integer(0), (v1, v2) -> v1 + v2);
            vo.setVisitSum(classVisitSum);
            Integer classVisitedSum = classRealMap.getOrDefault(e.getClassId(), 0);
            if (classVisitSum.equals(0)) {
                vo.setAvgOne(BigDecimal.ZERO);
            } else {
                vo.setAvgOne(BigDecimal.valueOf(classVisitSum).divide(BigDecimal.valueOf(e.getStudentNum()), 1, RoundingMode.HALF_UP));
            }
            if (classVisitedSum.equals(0)) {
                vo.setRate(BigDecimal.ZERO);
            } else {
                vo.setRate(BigDecimal.valueOf(classVisitedSum).divide(BigDecimal.valueOf(e.getStudentNum()), 2, RoundingMode.HALF_UP).multiply(new BigDecimal(100)));

            }
            vo.setVisitedSum(classVisitedSum);
            vo.setNotVisitSum(e.getStudentNum() - classVisitedSum);
            return vo;
        }).collect(Collectors.toList());
        ret.setClasses(classes);
        return ret;
    }

    public VisitStatisticsVo statisticsInterest(List<GetClazzWithStudentsRet> clazzWithStudents, List<String> classIds) {
        List<GetYearListRet> yearList = xgkService.getYearList(SecurityUtils.getAuthInfo().getOrgCode());
        if (yearList.isEmpty()) {
            throw new ServiceException("学年数据不存在");
        }
        long l = DateUtils.getNowyyyyMMdd().getTime();
        GetYearListRet curYear = yearList.stream().filter(e -> DateUtils.parseDate(e.getBeginDay()).getTime() <= l && DateUtils.parseDate(e.getEndDay()).getTime() >= l).findFirst().orElse(yearList.get(yearList.size() - 1));
        if (curYear == null) {
            throw new ServiceException("当前学年数据不存在");
        }
        List<VisitRecord> allStudent = visitInterestTagMapper.selectAllInterestSumGroupByClassIds(classIds);
//        List<VisitRecord> allStudent = visitRecordMapper.selectAllInterestSumGroupByClassIds(classIds);
        List<VisitRecord> visitCount = visitRecordMapper.selectInterestCountGroupByClassIds(classIds, DateUtils.parseDate(curYear.getBeginDay()), DateUtils.parseDate(curYear.getEndDay()));
        // 学生人数
        Integer allSum = allStudent.stream().map(VisitRecord::getCount).reduce(new Integer(0), (v1, v2) -> v1 + v2);
        // 合计完成家访
        Integer visitSum = visitCount.stream().map(VisitRecord::getCount).reduce(new Integer(0), (v1, v2) -> v1 + v2);
        Map<String, Integer> classRealMap = visitCount.stream().collect(Collectors.groupingBy(VisitRecord::getClassId))
                .entrySet().stream().collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue().size()));
        // 去重后真实家访次数
        Integer realVisitSum = classRealMap.values().stream().reduce(new Integer(0), (v1, v2) -> v1 + v2);
        VisitStatisticsVo ret = new VisitStatisticsVo();
        if (allSum.equals(0)) {
            realVisitSum = 0;
            visitSum = 0;
        }
        // 生均家访次数
        if (visitSum.equals(0)) {
            ret.setAvgOne(BigDecimal.ZERO);
        } else {
            BigDecimal personAvg = BigDecimal.valueOf(visitSum).divide(BigDecimal.valueOf(allSum), 1, RoundingMode.HALF_UP);
            ret.setAvgOne(personAvg);
        }
        ret.setVisitSum(visitSum);
        ret.setVisitedSum(realVisitSum);
        ret.setNotVisitSum(allSum - realVisitSum);
        if (realVisitSum.equals(0)) {
            ret.setRate(BigDecimal.ZERO);
        } else {
            ret.setRate(BigDecimal.valueOf(realVisitSum).divide(BigDecimal.valueOf(allSum), 3, RoundingMode.HALF_UP).multiply(new BigDecimal(100)));

        }

        // 计算班级统计详情
        Map<String, Integer> classStudentMap = allStudent.stream().collect(Collectors.toMap(VisitRecord::getClassId, VisitRecord::getCount));
        List<ClassStatisticsVo> classes = clazzWithStudents.stream().filter(e -> classIds.contains(e.getClassId())).map(e -> {
            ClassStatisticsVo vo = new ClassStatisticsVo();
            vo.setClassId(e.getClassId());
            vo.setClassName(e.getClassName());
            vo.setTeacherName(e.getTeacherName());
            Integer classVisitSum = visitCount.stream().filter(k -> e.getClassId().equals(k.getClassId()))
                    .map(VisitRecord::getCount).reduce(new Integer(0), (v1, v2) -> v1 + v2);
            vo.setVisitSum(classVisitSum);
            Integer studentNum = classStudentMap.getOrDefault(e.getClassId(), 0);
            Integer classVisitedSum = classRealMap.getOrDefault(e.getClassId(), 0);
            if (classVisitSum.equals(0)) {
                vo.setAvgOne(BigDecimal.ZERO);
            } else {
                vo.setAvgOne(BigDecimal.valueOf(classVisitSum).divide(BigDecimal.valueOf(studentNum), 1, RoundingMode.HALF_UP));
            }
            if (classVisitedSum.equals(0)) {
                vo.setRate(BigDecimal.ZERO);
            } else {
                vo.setRate(BigDecimal.valueOf(classVisitedSum).divide(BigDecimal.valueOf(studentNum), 2, RoundingMode.HALF_UP).multiply(new BigDecimal(100)));
            }
            vo.setVisitedSum(classVisitedSum);
            vo.setNotVisitSum(studentNum - classVisitedSum);
            return vo;
        }).collect(Collectors.toList());
        ret.setClasses(classes);
        return ret;
    }

    /**
     * 过呢根据所选层级获取班级id
     *
     * @param schoolPartTree
     * @param unitType
     * @param unitId
     * @return
     */
    private List<String> getClassIds(GetSchoolPartTreeRet schoolPartTree, Integer unitType, String unitId) {
        if (UnitTypeEnum.CLASS.getCode().equals(unitType)) {
            return Lists.newArrayList(unitId);
        } else {
            GetSchoolPartTreeRet tree = getTree(schoolPartTree, unitType, unitId, new GetSchoolPartTreeRet());
            if (tree == null) {
                return Lists.newArrayList();
            }
            List<String> classId = getClassIds(tree, Lists.newArrayList());
            return classId;
        }
    }

    /**
     * 获取叶子节点班级id
     *
     * @param schoolPartTree
     * @param ids
     * @return
     */
    private List<String> getClassIds(GetSchoolPartTreeRet schoolPartTree, List<String> ids) {
        if (UnitTypeEnum.CLASS.getCode().equals(schoolPartTree.getUnitType())) {
            ids.add(schoolPartTree.getUnitId());
        } else {
            for (GetSchoolPartTreeRet tree : schoolPartTree.getChildren()) {
                if (UnitTypeEnum.CLASS.getCode().equals(tree.getUnitType()) && UnitTypeEnum.CLASS.getCode().equals(tree.getUnitType())) {
                    ids.add(tree.getUnitId());
                } else {
                    ids = getClassIds(tree, ids);
                }
            }
        }
        return ids;
    }

    /**
     * 查找树枝
     *
     * @param schoolPartTree
     * @param unitType
     * @param unitId
     * @param ret
     * @return
     */
    private GetSchoolPartTreeRet getTree(GetSchoolPartTreeRet schoolPartTree, Integer unitType, String unitId, GetSchoolPartTreeRet ret) {
        if (schoolPartTree.getUnitType().equals(unitType) && schoolPartTree.getUnitId().equals(unitId)) {
            return schoolPartTree;
        } else if (unitType == null || StringUtils.isEmpty(unitId)) {
            return schoolPartTree;
        } else {
            for (GetSchoolPartTreeRet tree : schoolPartTree.getChildren()) {
                if (tree.getUnitType().equals(unitType) && tree.getUnitId().equals(unitId)) {
                    return tree;
                } else {
                    ret = getTree(tree, unitType, unitId, ret);
                }
            }
        }

        return ret;
    }


    /**
     * 家访列表查询
     *
     * @param dto
     * @return
     */
    public TableDataInfo listRecord(ListRecordDto dto) {
        VisitConditionEnum byCode;
        if (dto.getCondition() == null) {
            byCode = VisitConditionEnum.NO_CONDITION;
        } else {
            byCode = VisitConditionEnum.getByCode(dto.getCondition());
        }

//        List<GetClazzWithStudentsRet> clazzWithStudents = xgkService.getClazzWithStudents(SecurityUtils.getAuthInfo().getPersonId());
//        List<String> classIds = clazzWithStudents.stream().map(GetClazzWithStudentsRet::getClassId).collect(Collectors.toList());
//        List<String> classIds = SecurityUtils.getAuthInfo().getEclasses().stream().map(Eclass::getEclassId).collect(Collectors.toList());
        List<String> classIds = xgkService.mainClassId(SecurityUtils.getAuthInfo().getPersonId());
//        if (classIds.size() == 0) {
//            return new TableDataInfo(Lists.newArrayList(), 0);
//        }
        List<Long> recordIds;
        Long total;
        PageHelper.startPage(dto.getPageNum(), dto.getPageSize());
        switch (byCode) {
            case INTEREST:
                PageHelper.orderBy("t1.id desc");
                recordIds = visitRecordMapper.selectInterestIds(SecurityUtils.getAuthInfo().getOrgCode(), classIds, SecurityUtils.getAuthInfo().getPersonId());
                total = (new PageInfo(recordIds).getTotal());
                break;
            case HAS_PEERS:
                PageHelper.orderBy("t1.id desc");
                recordIds = visitRecordMapper.selectHasPeersIds(SecurityUtils.getAuthInfo().getOrgCode(), classIds, SecurityUtils.getAuthInfo().getPersonId());
                total = (new PageInfo(recordIds).getTotal());
                break;
            case HAS_SAFE_EVENT:
                VisitRecord query = new VisitRecord();
                query.setOrgCode(SecurityUtils.getAuthInfo().getOrgCode());
                query.setHasSafeEvent(BooleanEnum.TRUE.getCode());
                query.setIsDraft(BooleanEnum.FALSE.getCode());
                query.setClassIds(classIds);
                query.setCurrPersonId(SecurityUtils.getAuthInfo().getPersonId());
                PageHelper.orderBy("id desc");
                List<VisitRecord> visitRecords = visitRecordMapper.selectVisitRecordListV2(query);
                total = (new PageInfo(visitRecords).getTotal());
                recordIds = visitRecords.stream().map(VisitRecord::getId).collect(Collectors.toList());
                break;
            default:
                VisitRecord queryAll = new VisitRecord();
                queryAll.setOrgCode(SecurityUtils.getAuthInfo().getOrgCode());
                queryAll.setIsDraft(BooleanEnum.FALSE.getCode());
                queryAll.setClassIds(classIds);
                queryAll.setCurrPersonId(SecurityUtils.getAuthInfo().getPersonId());
                PageHelper.orderBy("id desc");
                List<VisitRecord> allVisitRecords = visitRecordMapper.selectVisitRecordListV2(queryAll);
                total = (new PageInfo(allVisitRecords).getTotal());
                recordIds = allVisitRecords.stream().map(VisitRecord::getId).collect(Collectors.toList());
                break;
        }

        if (recordIds.size() == 0) {
            TableDataInfo tableDataInfo = new TableDataInfo();
            tableDataInfo.setTotal(0);
            tableDataInfo.setRows(Lists.newArrayList());
            return tableDataInfo;
        }
        List<VisitRecord> visitRecords = visitRecordMapper.selectVisitRecordByIds(recordIds);
        Map<Long, List<VisitInterestTag>> tagMap = visitInterestTagMapper.selectVisitInterestTagByRecordIds(recordIds).stream().collect(Collectors.groupingBy(VisitInterestTag::getVisitRecordId));
        Map<Long, List<VisitPeers>> peerMap = visitPeersMapper.selectVisitPeersByRecordIds(recordIds).stream().collect(Collectors.groupingBy(VisitPeers::getRecordId));
        Map<Long, String> safeTextMap = visitRecordTextMapper.selectVisitRecordTextByRecordIds(recordIds).stream().collect(Collectors.toMap(VisitRecordText::getRecordId, VisitRecordText::getSafeRecord));
        List<ListRecordVo> ret = visitRecords.stream().map(e -> {
            ListRecordVo vo = new ListRecordVo();
            BeanUtils.copyProperties(e, vo);
            vo.setVisitTime(e.getVisitDate());
            vo.setSafeRecord(safeTextMap.get(e.getId()));
            if (tagMap.containsKey(e.getId())) {
                vo.setTags(tagMap.get(e.getId()).stream().map(k -> InterestEnum.getNameByCode(k.getTag())).collect(Collectors.toList()));
            }
            List<VisitPeers> orDefault = peerMap.getOrDefault(e.getId(), Lists.newArrayList());
            List<VisitPeer> peers = orDefault.stream().map(k -> {
                VisitPeer peerVo = new VisitPeer();
                BeanUtils.copyProperties(k, peerVo);
                return peerVo;
            }).collect(Collectors.toList());
            vo.setPeers(peers);
            return vo;
        }).collect(Collectors.toList());
        TableDataInfo tableDataInfo = new TableDataInfo(ret, total);
        tableDataInfo.setCode(HttpStatus.SUCCESS);
        return tableDataInfo;
    }

    /**
     * 新增家访记录
     *
     * @param visitRecord 家访记录
     * @return 结果
     */
    public int insertVisitRecord(VisitRecord visitRecord) {
        visitRecord.setCreateTime(DateUtils.getNowDate());
        return visitRecordMapper.insertVisitRecord(visitRecord);
    }

    public Long initRecord(String personId) {
        VisitRecord record = new VisitRecord();

        List<PersonInfoRet> personInfo = xgkService.getStudentByPersonIds(Lists.newArrayList(personId));
        if (personInfo.size() > 0) {
            PersonInfoRet personInfoRet = personInfo.get(0);
            record.setPersonId(personInfoRet.getPersonId());
            record.setPersonName(personInfoRet.getName());
        }
        AuthInfo authInfo = SecurityUtils.getAuthInfo();
        record.setCreateBy(authInfo.getPersonId());
        record.setCreateByName(authInfo.getName());
        record.setOrgCode(authInfo.getOrgCode());
        record.setIsDraft(BooleanEnum.TRUE.getCode());
        record.setDelStatus(BooleanEnum.TRUE.getCode());

        visitRecordMapper.insertVisitRecord(record);
        VisitRecordText visitRecordText = new VisitRecordText();
        visitRecordText.setRecordId(record.getId());
        visitRecordTextMapper.insertVisitRecordText(visitRecordText);

        return record.getId();
    }

    /**
     * 添加家访记录
     *
     * @param dto
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean addVisitRecord(AddVisitRecordDto dto) {
        VisitRecord record = new VisitRecord();
        record.setId(dto.getRecordId());
        record.setIsDraft(dto.getIsDraft());
        record.setVisitAddr(dto.getVisitAddr());
        record.setHasSafeEvent(dto.getHasSafeEvent());
        record.setVisitDate(dto.getVisitTime());


        VisitRecordText text = new VisitRecordText();
        text.setRecordId(dto.getRecordId());
        text.setVisitRecord(dto.getVisitRecord());
        text.setSafeRecord(dto.getSafeRecord());
        text.setInterestRecord(dto.getInterestRecord());

        List<VisitImg> visitImg = dto.getVisitImg().stream().map(e -> {
            VisitImg img = new VisitImg();
            img.setRecordId(dto.getRecordId());
            img.setImgType(VisitImgTypeEnum.VISIT.getCode());
            img.setUrl(e);
            return img;
        }).collect(Collectors.toList());
        //添加家访记录现场图片
        List<String> visitSceneImg = dto.getVisitSceneImg();
        if (!CollectionUtils.isEmpty(visitSceneImg)) {
            visitSceneImg.forEach(e -> {
                if (StringUtils.isEmpty(e)) {
                    return;
                }

                VisitImg img = new VisitImg();
                img.setRecordId(dto.getRecordId());
                img.setImgType(VisitImgTypeEnum.SCENE.getCode());
                img.setUrl(e);
                visitImg.add(img);
            });
        }
        if (dto.getInterestImg() != null && dto.getInterestImg().size() > 0) {
            List<VisitImg> interestImg = dto.getInterestImg().stream().map(e -> {
                VisitImg img = new VisitImg();
                img.setRecordId(dto.getRecordId());
                img.setImgType(VisitImgTypeEnum.INTEREST.getCode());
                img.setUrl(e);
                return img;
            }).collect(Collectors.toList());
            visitImg.addAll(interestImg);
        }

        List<VisitImg> safeImg = dto.getSafeImg().stream().map(e -> {
            VisitImg img = new VisitImg();
            img.setRecordId(dto.getRecordId());
            img.setImgType(VisitImgTypeEnum.SAFE.getCode());
            img.setUrl(e);
            return img;
        }).collect(Collectors.toList());
        visitImg.addAll(safeImg);

        // 是否第一次家访
        boolean isFirstEdit = true;
        VisitRecord record1 = visitRecordMapper.selectVisitRecordById(dto.getRecordId());
        if (record1 != null && record1.getReservationId() != null) {
            VisitReservation visitReservation = visitReservationMapper.selectVisitReservationById(record1.getReservationId());
            if (BooleanEnum.TRUE.getCode().equals(visitReservation.getIsVisited())) {
                isFirstEdit = false;
            }
            // 修改为已家访
            if (visitReservation.getCreateBy().equals(SecurityUtils.getAuthInfo().getPersonId())) {
                visitReservation.setIsVisited(BooleanEnum.TRUE.getCode());
                visitReservation.setStatus(BooleanEnum.TRUE.getCode());
                visitReservationMapper.updateVisitReservation(visitReservation);
                visitReservationService.sendPassMsg(visitReservationService.getParentsIds(record1.getPersonId()), record1.getPersonId(), record1.getReservationId(), false);
            }
        } else if (record1 != null && BooleanEnum.FALSE.getCode().equals(record1.getIsDraft())) {
            isFirstEdit = false;
        } else {
            isFirstEdit = true;
        }

        if (isFirstEdit) {
            List<VisitRecord> visitCount = visitRecordMapper.selectCountGroupByPersonIds(Lists.newArrayList(record1.getPersonId()));
            if (visitCount.size() != 0) {
                Integer count = visitCount.get(0).getCount();
                String name = "第" + (count + 1) + "次家访";
                record.setRecordName(name);
            } else {
                record.setRecordName("第1次家访");
            }
        }

        List<PersonInfoRet> personInfo = xgkService.getStudentByPersonIds(Lists.newArrayList(record1.getPersonId()));
        if (personInfo.size() > 0) {
            PersonInfoRet personInfoRet = personInfo.get(0);
            record.setClassId(personInfoRet.getCurrentClass());
            record.setClassName(personInfoRet.getCurrentClassName());
            record.setSex(personInfoRet.getSex());
        }

        // 更新重点标签
        UpdateTagsDto tag = new UpdateTagsDto();
        tag.setPersonId(record1.getPersonId());
        tag.setRecordId(record1.getId());
        tag.setTags(dto.getTags());
        visitInterestTagService.updateTags(tag);

        visitRecordMapper.updateVisitRecord(record);
        visitRecordTextMapper.updateVisitRecordText(text);
        visitImgMapper.deleteByRecordId(dto.getRecordId());
        if (visitImg.size() > 0) {
            visitImgMapper.batchInsert(visitImg);
        }
        return true;
    }

    public GetVisitRecordDto getRecordInfo(Long recordId) {
        VisitRecord record = visitRecordMapper.selectVisitRecordById(recordId);
        VisitImg imgQuery = new VisitImg();
        imgQuery.setRecordId(recordId);
        VisitRecordText text = visitRecordTextMapper.selectVisitRecordTextByRecordId(recordId);
        List<VisitImg> visitImgs = visitImgMapper.selectVisitImgList(imgQuery);
        VisitInterestTag tagQuery = new VisitInterestTag();
        tagQuery.setVisitRecordId(recordId);
        tagQuery.setDataType(VisitDataTypeEnum.RECORD.getCode());
        List<VisitInterestTag> tags = visitInterestTagMapper.selectVisitInterestTagList(tagQuery);
        tags.stream().forEach(e -> {
            e.setTagStr(InterestEnum.getNameByCode(e.getTag()));
        });
        List<VisitImg> visit = visitImgs.stream().filter(e -> VisitImgTypeEnum.VISIT.getCode().equals(e.getImgType())).collect(Collectors.toList());
        List<VisitImg> interest = visitImgs.stream().filter(e -> VisitImgTypeEnum.INTEREST.getCode().equals(e.getImgType())).collect(Collectors.toList());
        List<VisitImg> safe = visitImgs.stream().filter(e -> VisitImgTypeEnum.SAFE.getCode().equals(e.getImgType())).collect(Collectors.toList());
        List<VisitImg> scene = visitImgs.stream().filter(e -> VisitImgTypeEnum.SCENE.getCode().equals(e.getImgType())).collect(Collectors.toList());
        GetVisitRecordDto dto = new GetVisitRecordDto();
        BeanUtils.copyProperties(record, dto);
        if (text != null) {
            BeanUtils.copyProperties(text, dto);
        }
        dto.setVisitImg(visit.stream().map(VisitImg::getUrl).collect(Collectors.toList()));
        dto.setVisitSceneImg(scene.stream().map(VisitImg::getUrl).collect(Collectors.toList()));
        dto.setInterestImg(interest.stream().map(VisitImg::getUrl).collect(Collectors.toList()));
        dto.setVisitTime(record.getVisitDate());
        dto.setSafeImg(safe.stream().map(VisitImg::getUrl).collect(Collectors.toList()));
        dto.setRecordTags(tags);
        String appointmentId = record.getCreateBy();
        if (ObjectUtils.isNotEmpty(record.getReservationId())) {
            VisitReservation reservation = visitReservationMapper.selectVisitReservationById(record.getReservationId());
            appointmentId = reservation.getCreateBy();
        }
        dto.setAppointmentId(appointmentId);
        return dto;
    }

    /**
     * 修改家访记录
     *
     * @param visitRecord 家访记录
     * @return 结果
     */
    public int updateVisitRecord(VisitRecord visitRecord) {
        visitRecord.setUpdateTime(DateUtils.getNowDate());
        return visitRecordMapper.updateVisitRecord(visitRecord);
    }

    /**
     * 批量删除家访记录
     *
     * @param ids 需要删除的家访记录主键
     * @return 结果
     */
    public int deleteVisitRecordByIds(Long[] ids) {
        return visitRecordMapper.deleteVisitRecordByIds(ids);
    }

    /**
     * 删除家访记录信息
     *
     * @param id 家访记录主键
     * @return 结果
     */
    public int deleteVisitRecordById(Long id) {
        VisitReservation reservation = visitReservationMapper.selectVisitReservationById(id);
        if (ObjectUtils.isNotEmpty(reservation) && !reservation.getCreateBy().equals(SecurityUtils.getAuthInfo().getPersonId())) {
            throw new ServiceException("只能删除自己的家访记录信息");
        }
        VisitRecord update = new VisitRecord();
        update.setId(id);
        update.setDelStatus(BooleanEnum.FALSE.getCode());
        return visitRecordMapper.deleteVisitRecordById(id);
    }

    /**
     * 统计指定学校下的家访数据
     *
     * @return 统计结果
     */
    public VisitStatisticsVo statisticsAllBySchoolId() {
        GetSchoolPartTreeRet schoolPartTree = xgkService.getSchoolPartTree(SecurityUtils.getAuthInfo().getPersonId());
        List<String> classIds = getClassIds(schoolPartTree, new ArrayList<>(0));
        List<GetClazzWithStudentsRet> clazzWithStudents = xgkService.getClazzWithStudents(SecurityUtils.getAuthInfo().getPersonId());

        if (classIds.size() == 0) {
            classIds = Lists.newArrayList("-1");
        }
        return statisticsAll(clazzWithStudents, classIds);
    }

    public VisitStatisticsVo statisticsAllBySchoolCode(String orgCode) {
        VisitStatisticsVo result = new VisitStatisticsVo();
        XgkListResp<SchoolRet> data = xgkService.getStudentCountsByOrgCode(orgCode);
        //获取学生总数
        String studentCount;
        if (ObjectUtils.isEmpty(data) || ObjectUtils.isEmpty(data.getData()) || ObjectUtils.isEmpty(data.getData().get(0))) {
            studentCount = "0";
        }else {
            studentCount = data.getData().get(0).getStudentCount();
        }
        //查询有效的总家访记录
        LambdaQueryWrapper<VisitRecord> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper
                .select(VisitRecord::getPersonId)
                .eq(VisitRecord::getDelStatus, "1")
                .eq(VisitRecord::getOrgCode, orgCode)
                .eq(VisitRecord::getIsDraft,BooleanEnum.FALSE.getStrCode());
        List<VisitRecord> visitRecords = visitRecordMapper.selectList(queryWrapper);
        if (ObjectUtils.isEmpty(visitRecords)) {
            //无家访记录
            visitRecords = new ArrayList<>(0);
        }
        //已完成家访的学生
        Set<String> haveVisitedSet = visitRecords.stream().map(VisitRecord::getPersonId).collect(Collectors.toSet());
        //计算家访比例
        result.setRate(new BigDecimal(haveVisitedSet.size()).divide(new BigDecimal(studentCount), 3, RoundingMode.HALF_UP).multiply(new BigDecimal(100)));
        //计算已完成
        result.setVisitedSum(haveVisitedSet.size());
        //计算未完成
        result.setNotVisitSum(Integer.parseInt(studentCount) - haveVisitedSet.size());
        //合计完成家访次数
        result.setVisitSum(visitRecords.size());
        //生均家访次数
        result.setAvgOne(new BigDecimal(visitRecords.size()).divide(new BigDecimal(studentCount), 3, RoundingMode.HALF_UP));
        return result;

    }
}
